<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;
use PhpAmqpLib\Connection\AMQPStreamConnection;
use PhpAmqpLib\Message\AMQPMessage;
class RabbitmqConsumerCommand extends Command
{
    /**
     * The name and signature of the console command.
     * @var string
     */
    protected $signature = 'rabbitmq_consumer';//给消费者起个command名称

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Command description';

    /**
     * Create a new command instance.
     *
     * @return void
     */
    public function __construct()
    {
        parent::__construct();
    }

    /**
     * Execute the console command.
     *
     * @return int
     */
    public function handle()
    {
        $this->subscribe();
    }
    /**
     * 发布订阅模式 -订阅
     * publish-and- subscribe， 即发布订阅模型。在Pub/Sub模型中，生产者将消息发布到一个主题(Topic)中，订阅了该Topic的所有下游消费者，都可以接收到这条消息。
     * Author: 王金玉
     * Date: 2023/5/4
     * Time: 16:10
     */
    public function subscribe()
    {
        //创建服务器连接
        $connection = new AMQPStreamConnection('43.142.255.59', 5672, 'guest', 'guest');
        //连接信道
        //信道是生产消费者与rabbit通信的渠道，生产者publish或者消费者消费一个队列都是需要通过信道来通信的
        //信道是建立在TCP上面的虚拟链接，也就是rabbitMQ在一个TCP上面建立成百上千的信道来达到多个线程处理。
        //注意是一个TCP 被多个线程共享，每个线程对应一个信道，信道在rabbit都有唯一的ID，保证了信道的私有性，对应上唯一的线程使用。
        $channel = $connection->channel();

        //channel->queue_declare通过信道创建一个是否是持久化的消息队列
        //queue第一个参数代表消息队列名称
       $channel->queue_declare('test', false, false, false, false);

        echo " [*] Waiting for messages. To exit press CTRL+C\n";

        //进行监听消费者是否有消息，如果有进行输出消息内容
        $callback = function ($msg) {
            echo ' 我是订阅者开始进行消费[x] ', $msg->body, "\n";
        };

        //通过信道进行消费消息
        $channel->basic_consume('test', '', false, true, false, false, $callback);

        //如果信道是打开状态
        while(count($channel->callbacks)) {
            $channel->wait();
        }

        //关闭信道
        $channel->close();
        //关闭连接
        $connection->close();
    }
}
